﻿#define Asynchronous 0 // 0-同步模式；1-异步模式
#define PRO_USE_VAR_ARGS
#include <ProToolkitErrors.h>
#include <ProMenuBar.h>
#include <ProUtil.h>
#include <ProTKRunTime.h>
#include <ProMessage.h>
#include <ProModelitem.h>
#include <ProWindows.h>
#include <ProWstring.h>
#include <ProArray.h>
#include <ProFeature.h>
#include <ProFeatType.h>
#include <ProSolid.h>
#include <ProAsmcomp.h>
#include <ProUIMessage.h>
#include <ProVariantFeat.h>
#include <ProLayer.h>
#include <ProLayerstate.h>
#include <ProSimprep.h>
#include <ProSelbuffer.h>
#include <ProDrawing.h>
#include <ProMenu.h>

#include "OTKXString.cpp"
#include "logger.cpp"
#include "wxyutils.cpp"
#include <wfcSession.h>
// #include <afxtempl.h>
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
#include "sqlite3.h"

#define MSGFILE "CreoTool.txt"
#define MAPKEY_SIZE 1000

string LogFile[] = {"Info.log", "warn.log", "error.log"};
#define CALL_REPORT(call, from, status, error)                        \
    {                                                                 \
        if (error)                                                    \
            LOG(LOG_ERROR) << call << "\t" << from << "\t" << status; \
    }
#define CALL_EXIT(call, from, status, error)                          \
    {                                                                 \
        if (error)                                                    \
        {                                                             \
            LOG(LOG_ERROR) << call << "\t" << from << "\t" << status; \
            return 0;                                                 \
        }                                                             \
    }

//全局变量
const char *ProjectName = "CreoTool";
string dllpath;
ProFileName msg_filename;

#ifdef GetMessage
#define GetMessage GetMessage
#endif

//函数声明
namespace drawingModule
{
    //打开工程图
    int OpenDrw();
    //创建工程图
    int CreateDrw();
    int CreateDrwByFormat(string format_name);
    int CreatDrwByA4Prt(ProAppData app_data, int app_int);
    ProError CreateDrwByA4Prt();
}
//显示帮助信息
int Info();

namespace assem
{
    //随机着色
    int ColorPaint();
    double _myand();
    int RepaintPart(ProModelitem modelitem);
    int Repaint(ProFeature feature);
    ProError AsmVisitAcFn(ProFeature *p_object, ProError status, vector<ProFeature> *app_data);
    ProError AsmCompFilter(ProFeature *feature, ProAppData app_data);
}
//内嵌Lua
int lua_test();
ProError ShowDialog(wchar_t *Message);

//内嵌sqlite测试
int sqlite_test();
int callback(void *, int nCount, char **pValue, char **pName);
namespace SimprepModule
{
    //模型显示
    //全部显示
    int ShowAll();
    //隐藏
    int HideSel();
    //只显示
    int ShowSel();
    //反向显示
    int ReHide();
    ProError SimprepdataitemsvisitActFn(ProSimprepitem *item, ProError err, ProAppData app_data);
    //复制当前简化表示数据
    ProError SimprepdataCopy(ProSimprepitem *item, ProError err, ProAppData app_data);
    //反显当前简化表示数据
    ProError SimprepdataRev(ProSimprepitem *item, ProError err, ProAppData app_data);
    int SimprepdataitemAdd(ProSimprep rep, ProSelection sel, ProSimprepActionType act_type);
    ProError HideitemActFn(ProFeature *feat, ProError err, ProAppData app_data);
}
namespace layer
{
    int HideAll();
    ProError HideAllActFn(ProFeature *p_object, ProError status, vector<ProFeature> *app_data);
}

//清理日志
void cleanlog();

static uiCmdAccessState DefaultAccess(uiCmdAccessMode access_mode)
{
    return (ACCESS_AVAILABLE);
}
namespace drawingModule
{
#define otk_model 1

    //打开工程图
    int OpenDrw()
    {
        //选择模型，默认打开当前模型
        ProError err;
        ProSelection *p_sel;
        ProMdl mdl;
        ProModelitem mdl_item;
        bool status;
        int n_sel;
        err = ProSelect((char *)"prt_or_asm", 1, NULL, NULL, NULL, NULL, &p_sel, &n_sel);
        CALL_REPORT("ProSelect()", "Action()", err, err != PRO_TK_NO_ERROR);
        if (err == PRO_TK_NO_ERROR && n_sel > 0)
        {
            err = ProSelectionModelitemGet(p_sel[0], &mdl_item);
            CALL_EXIT("ProSelectionModelitemGet", "OpenDrw", err, err != PRO_TK_NO_ERROR);
            err = ProModelitemMdlGet(&mdl_item, &mdl);
            CALL_EXIT("ProModelitemMdlGet", "OpenDrw", err, err != PRO_TK_NO_ERROR);
            err = ProSelectionUnhighlight(p_sel[0]);
            CALL_EXIT("ProSelectionUnhighlight", "OpenDrw", err, err != PRO_TK_NO_ERROR);
        }
        else
        {
            err = ProMdlCurrentGet(&mdl);
            CALL_EXIT("ProMdlCurrentGet", "OpenDrw", err, err != PRO_TK_NO_ERROR);
        }

        //获取当前模型fullname
        ProMdlName mdl_name;
        err = ProMdlMdlnameGet(mdl, mdl_name);
        CALL_EXIT("ProMdlOriginGet", "OpenDrw", err, err != PRO_TK_NO_ERROR);
        char cmdl_name[PRO_PATH_SIZE];
        ProWstringToString(cmdl_name, mdl_name);

        //获取模型目录
        ProPath mdl_origin;
        err = ProMdlOriginGet(mdl, mdl_origin);
        char cmdl_origin[PRO_PATH_SIZE];
        ProWstringToString(cmdl_origin, mdl_origin);
        char drive[_MAX_DRIVE];
        char dir[_MAX_DIR];
        char fname[_MAX_FNAME];
        char ext[_MAX_EXT];
        _splitpath(cmdl_origin, drive, dir, fname, ext);
        //创建工程图文件名：模型fullname+.drw
        char cfilename[PRO_PATH_SIZE];
        ProTKSprintf(cfilename, "%s.drw", cmdl_name);
        // ProTKSprintf(cfilename, "%s%s%s.drw", drive, dir, cmdl_name);
        //检索工程图
        ProDrawing drw;
        ProFamilyMdlName filename;
        ProStringToWstring(filename, cfilename);

        // toolkit检索无法指定目录，自动搜索工作目录-服务器
        err = ProMdlnameRetrieve(filename, PRO_MDLFILE_DRAWING, (ProMdl *)&drw);
        //本地非当前会话中工程图需要完整目录，虽然会报错PRO_TK_GENERAL_ERROR,但是可以打开
        status = (err != PRO_TK_NO_ERROR);
        if (status)
        {
            ProMessageDisplay(msg_filename, "%0s is not found!", cfilename);
            CALL_EXIT("ProMdlnameRetrieve", "OpenDrw", err, status);
        }
        else
        {
            //显示模型
            ProMdlName object_name;
            err = ProMdlMdlnameGet((ProMdl)drw, object_name);
            CALL_EXIT("ProMdlMdlnameGet", "OpenDrw", err, err != PRO_TK_NO_ERROR);
            int win_id;
            err = ProObjectwindowMdlnameCreate(object_name, PRO_DRAWING, &win_id);
            CALL_EXIT("ProObjectwindowMdlnameCreate", "OpenDrw", err, err != PRO_TK_NO_ERROR);
            err = ProMdlDisplay((ProMdl)drw);
            CALL_EXIT("ProMdlDisplay", "OpenDrw", err, err != PRO_TK_NO_ERROR);
            err = ProWindowActivate(win_id);
            CALL_EXIT("ProWindowActivate", "OpenDrw", err, err != PRO_TK_NO_ERROR);
        }

        return 0;
    }

#if otk_model

    //创建同名工程图
    int CreateDrw()
    /*
    {
        ProError err;
        int menu_id;
        err = ProMenuFileRegister((char *)"CreateDrw", (char *)"CreateDrw.mnu", &menu_id);
        CALL_REPORT("ProMenuFileRegister", "CreateDrw", err, err != PRO_TK_NO_ERROR);
        // err = ProMenuAuxfileRegister((char *)"CreateDrw", (char *)"CreateDrw.aux", &menu_id);
        // CALL_REPORT("ProMenubuttonActionSet", "CreateDrw", err, err != PRO_TK_NO_ERROR);
        ProAppData app_data;
        int app_int;
        err = ProMenubuttonActionSet((char *)"CreateDrw", (char *)"a4_prt_dreami", (ProMenubuttonAction)CreatDrwByA4Prt, NULL, 0);
        CALL_REPORT("ProMenubuttonActionSet", "CreateDrw", err, err != PRO_TK_NO_ERROR);
        ProMenubuttonActionSet((char *)"CreateDrw", (char *)"Done", (ProMenubuttonAction)ProMenuDelete, NULL, 0);
        err = ProMenuCreate(PROMENUTYPE_MAIN, (char *)"CreateDrw", &menu_id);
        CALL_REPORT("ProMenuCreate", "CreateDrw", err, err != PRO_TK_NO_ERROR);
        int action;
        ProMenuProcess((char *)"", &action);
        // ProMacroExecute();

        return 0;
    }
    int CreatDrwByA4Prt(ProAppData app_data, int app_int)
    {
        LOG(LOG_INFO) << "CreateA4";
        CreateDrwByFormat("a4_prt_dreami");
        return 0;
    }
    ProError CreateDrwByA4Prt()
    {
        LOG(LOG_INFO) << "CreateA4";
        CreateDrwByFormat("a4_prt_dreami");
        return PRO_TK_NO_ERROR;
    }

    int CreateDrwByFormat(string format_name)
    */
    {
        pfcSession_ptr session = pfcGetProESession();
        pfcModel_ptr model = session->GetCurrentModel();
        xstring common_name = model->GetCommonName();
        xstring file_name = model->GetFullName();
        try
        {
            string buf;
            // session->RunMacro("~ Activate `dwg_create` `psh_ok`");
            // buf = "~ Update `dwg_create` `opt_format_name` `" + format_name + ".frm`";
            // session->RunMacro(buf.c_str());
            // buf = "~ Input `dwg_create` `opt_format_name` `" + format_name + ".frm`";
            // session->RunMacro(buf.c_str());
            session->RunMacro("~ Select `dwg_create` `rad_format` 1 `2`");
            session->RunMacro("~ Activate `new` `OK`");
            session->RunMacro("~ Activate `new` `chk_use_default_template` 0");
            buf = "~ Update `new` `InputPanel2` `" + common_name + "`";
            session->RunMacro(buf.c_str());
            session->RunMacro("~ FocusIn `new` `InputPanel2`");
            buf = "~ Update `new` `InputPanel1` `" + file_name + "`";
            session->RunMacro(buf.c_str());
            buf = "~ Input `new` `InputPanel1` `" + file_name + "`";
            session->RunMacro(buf.c_str());
            session->RunMacro("~ FocusIn `new` `InputPanel1`");
            session->RunMacro("~ Select `new` `Type` 1 `Drawing`");
            session->RunMacro("~ Command `ProCmdModelNew` ");
            // wfcWSession_ptr wsession = wfcWSession::cast(session);
            // wsession->ExecuteMacro();
        }
        OTK_EXCEPTION_PRINT_LOG
        return 0;
    }

#else

    //创建工程图
    int CreateDrw()
    {
        ProError err;
        ProSelection *p_sel;
        ProMdl mdl;
        ProModelitem mdl_item;
        bool status;

        err = ProMdlCurrentGet(&mdl);
        CALL_EXIT("ProMdlCurrentGet", "CreateDrw", err, err != PRO_TK_NO_ERROR);

        //获取当前模型fullname
        ProMdlName mdl_name;
        err = ProMdlMdlnameGet(mdl, mdl_name);
        CALL_EXIT("ProMdlOriginGet", "CreateDrw", err, err != PRO_TK_NO_ERROR);
        char cmdl_name[PRO_NAME_SIZE];
        ProWstringToString(cmdl_name, mdl_name);
        wchar_t **common_name;
        ProFileName c_name;
        ProStringToWstring(c_name, cmdl_name);
        ProArrayAlloc(1, PRO_NAME_SIZE, 1, (ProArray *)common_name);
        ProArrayObjectAdd((ProArray *)common_name, 0, 1, c_name);
        ProBoolean c_flag;
        err = ProMdlCommonnameGet(mdl, common_name, &c_flag);
        CALL_EXIT("ProMdlCommonnameGet", "CreateDrw", err, err != PRO_TK_NO_ERROR);
        char c_common_name[PRO_NAME_SIZE];
        ProWstringToString(c_common_name, common_name[0]);
        ProArrayFree((ProArray *)common_name);

        // ProName option;
        // ProStringToWstring(option, "mapkey");
        // ProPath opt_value;
        // char combine_value[MAPKEY_SIZE];
        // char *tmp_value[] = {"%s @MAPKEY_LABEL%s; ",
        //                      "~ Command `ProCmdModelNew` ; ",
        //                      "~ Select `new` `Type` 1 `Drawing`; ",
        //                      "~ Input `new` `InputPanel1` `%s`; ",
        //                      "~ Update `new` `InputPanel1` `%s`; ",
        //                      "~ Update `new` `InputPanel2` `%s`; ",
        //                      "~ Activate `new` `chk_use_default_template` 0; ",
        //                      "~ Activate `new` `OK`; "};
        // char *tmp_value_combine = (char *)malloc(MAPKEY_SIZE);
        // //初始tmp_value_combine非空，直接strcat前面会有乱码
        // strcpy(tmp_value_combine, tmp_value[0]);
        // for (int s = 1; s < sizeof(tmp_value) / sizeof(tmp_value[0]); s++)
        // {
        //     strcat(tmp_value_combine, tmp_value[s]);
        // }
        // ProTKSprintf(combine_value, tmp_value_combine, "/scd", "create_drw", cmdl_name, cmdl_name, c_common_name);
        // ProStringToWstring(opt_value, combine_value);
        // err = ProConfigoptSet(option, opt_value);

        wchar_t *buffer = (wchar_t *)malloc(MAPKEY_SIZE);
        ProTKSwprintf(buffer, L"~ Update `new` `InputPanel2` `%s`", c_common_name);
        err = ProMacroLoad(buffer);
        err = ProMacroLoad(L"~ FocusIn `new` `InputPanel2`");
        ProTKSwprintf(buffer, L"~ Update `new` `InputPanel1` `%s`", cmdl_name);
        err = ProMacroLoad(buffer);
        ProTKSwprintf(buffer, L"~ Input `new` `InputPanel1` `%s`", cmdl_name);
        err = ProMacroLoad(buffer);
        err = ProMacroLoad(L"~ FocusIn `new` `InputPanel1`");
        err = ProMacroLoad(L"~ Select `new` `Type` 1 `Drawing`");
        err = ProMacroLoad(L"~ Command `ProCmdModelNew` ");

        // free(buffer);
        // free(tmp_value_combine);
        CALL_EXIT("ProMacroLoad", "CreateDrw", err, err != PRO_TK_NO_ERROR);
        return 0;
    }

#endif
}
namespace assem
{
    //随机着色

    int ColorPaint()
    {
        ProError status;
        ProMdl mdl;
        vector<ProFeature> feat_list;
        status = ProMdlCurrentGet(&mdl);
        srand((unsigned int)time(0));
        //遍历模型树
        status = ProSolidFeatVisit((ProSolid)mdl, (ProFeatureVisitAction)AsmVisitAcFn, AsmCompFilter, (vector<ProFeature> *)&feat_list);
        status = ProWindowRepaint(PRO_VALUE_UNUSED);
        return 0;
    }

    ProError AsmCompFilter(ProFeature *feature, ProAppData app_data)
    {
        ProError status;
        ProFeattype ftype;
        status = ProFeatureTypeGet(feature, &ftype);
        if (ftype == PRO_FEAT_COMPONENT)
            return PRO_TK_NO_ERROR;
        return PRO_TK_CONTINUE;
    }

    ProError AsmVisitAcFn(ProFeature *p_object, ProError status, vector<ProFeature> *app_data)
    {
        ProBoolean isVisible;
        ProFeatStatus p_status;
        ProMdl mdl;
        ProModelitem modelitem;

        status = ProFeatureStatusGet(p_object, &p_status);
        status = ProFeatureVisibilityGet(p_object, &isVisible);
        if (isVisible == PRO_B_TRUE && p_status != PRO_FEAT_SUPPRESSED)
        {
            status = ProAsmcompMdlGet((ProAsmcomp *)(p_object), (ProMdl *)&mdl);
            status = ProMdlToModelitem(mdl, &modelitem);
            if (modelitem.type == PRO_ASSEMBLY)
            {
                status = ProSolidFeatVisit((ProSolid)mdl, (ProFeatureVisitAction)AsmVisitAcFn, AsmCompFilter, app_data);
            }
            else
            {
                RepaintPart(modelitem);
                Repaint(*p_object);
            }
        }
        return PRO_TK_NO_ERROR;
    }
    int RepaintPart(ProModelitem modelitem)
    {
        ProError status;
        ProSurfaceAppearanceProps proprop_orig;
        status = ProSurfaceAppearancepropsGet(&modelitem, &proprop_orig);
        // status = ProMdlVisibleAppearancepropsGet(&((ProAsmitem)modelitem), &proprop_orig);
        ProSurfaceAppearanceProps proprop = {0.8, 0.8, 0.7, 0.6, 0.0, {_myand(), _myand(), _myand()}, {0, 0, 1}, proprop_orig.reflection, *proprop_orig.name, *proprop_orig.label, *proprop_orig.description, *proprop_orig.keywords};
        status = ProSurfaceAppearancepropsSet(&modelitem, &proprop);
        return 0;
    }
    int Repaint(ProFeature feature)
    {
        ProError status;
        ProSelection p_sel;
        status = ProFeatureSelectionGet(&feature, &p_sel);
        CALL_EXIT("ProFeatureSelectionGet", "RepaintPart", status, status != PRO_TK_NO_ERROR);
        ProMdl mdl;
        status = ProAsmcompMdlGet((ProAsmcomp *)(&feature), &mdl);
        ProBoolean flag;
        status = ProMdlIsVariantfeatMdl(mdl, &flag);
        LOG(LOG_INFO) << flag;
        ProAsmitem asm_item;
        ProAsmcomppath comppath;
        status = ProSelectionAsmcomppathGet(p_sel, &comppath);
        int item_id;
        ProType item_type;
        ProName item_name;
        ProModelitem mdlitem;
        status = ProMdlToModelitem(mdl, &mdlitem);
        status = ProMdlIdGet(mdl, &item_id);
        status = ProMdlTypeGet(mdl, (ProMdlType *)(&item_type));
        status = ProMdlNameGet(mdl, item_name);
        status = ProAsmcompAsmitemInit(mdl, item_id, mdlitem.type, item_name, &comppath, &asm_item);
        char name[100];
        ProWstringToString(name, item_name);
        LOG(LOG_INFO) << "id:" << mdlitem.id << "\ttype:" << mdlitem.type << "\tname:" << name;
        CALL_EXIT("ProAsmcompAsmitemInit", "RepaintPart", status, status != PRO_TK_NO_ERROR);
        ProSurfaceAppearanceProps proprop_orig;
        status = ProMdlVisibleAppearancepropsGet(&asm_item, &proprop_orig);
        CALL_EXIT("ProMdlVisibleAppearancepropsGet", "RepaintPart", status, status != PRO_TK_NO_ERROR);
        ProSurfaceAppearanceProps proprop = {0.8, 0.8, 0.7, 0.6, 0.0, {_myand(), _myand(), _myand()}, {0, 0, 1}, proprop_orig.reflection, *proprop_orig.name, *proprop_orig.label, *proprop_orig.description, *proprop_orig.keywords};
        status = ProMdlVisibleAppearancepropsSet(&asm_item, &proprop);
        CALL_EXIT("ProMdlVisibleAppearancepropsSet", "RepaintPart", status, status != PRO_TK_NO_ERROR);
        return 0;
    }
    double _myand()
    {
        return (double)(rand() % 1001) * 0.001f;
    }
}
//显示帮助信息
int Info()
{
    char guide_file[PRO_PATH_SIZE];
    ProTKSprintf(guide_file, "%stext\\guide.txt", dllpath.c_str());
    ProPath filepath;
    ProStringToWstring(filepath, guide_file);
    ProInfoWindowDisplay(filepath, NULL, NULL);
    return 0;
}
//清理日志文件
void cleanlog()
{
    LOG(LOG_FATAL); //触发logger析构函数
    fstream file;
    for (int i = 0; i < 3; i++)
    {
        file.open(LogFile[i], ios::in);
        if (file.get() == EOF)
        {
            file.close();
            file.clear();
            _FileExt emptyfile(LogFile[i].c_str());
            DeleteFileA(emptyfile.fullname.c_str());
        }
        else
        {
            file.close();
            file.clear();
        }
    }
}

//内嵌Lua测试
int lua_test()
{
    int sum;
    WCHAR buf[5];

    lua_State *L;
    L = luaL_newstate();
    luaopen_base(L);
    luaL_openlibs(L);
    string lua_file = dllpath + "src\\add.lua";
    luaL_loadfile(L, lua_file.c_str());
    lua_pcall(L, 0, LUA_MULTRET, 0);
    lua_getglobal(L, "add");
    lua_pushnumber(L, 1);
    lua_pushnumber(L, 2);
    lua_call(L, 2, 1);
    sum = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);
    lua_close(L);
    wsprintfW(buf, L"%d", sum);

    ProError err;
    err = ShowDialog(buf);
    return 0;
}

int sqlite_test()
{
    ProError err;
    sqlite3 *db;
    string db_file = dllpath + "test.db";
    char *sql = "SELECT * FROM TEST";
    char *zErrrMsg = 0;
    err = ShowDialog(L"程序已启动,准备打开数据库。");
    int res = sqlite3_open(db_file.c_str(), &db);
    if (res != SQLITE_OK)
    {
        err = ShowDialog(L"数据库打开失败。");
        return 0;
    }
    res = sqlite3_exec(db, sql, callback, NULL, &zErrrMsg);
    sqlite3_free(zErrrMsg);
    sqlite3_close(db);
    return 0;
}

int callback(void *, int nCount, char **pValue, char **pName)
{
    string str;
    for (int i = 0; i < nCount; i++)
    {
        char buf[100];
        ProTKSprintf(buf, "%s    %s\n", pName[i], pValue[i]);
        str += buf;
    }
    wchar_t msg[1000];
    ProStringToWstring(msg, (char *)str.c_str());
    ShowDialog(msg);
    return 0;
}

ProError ShowDialog(wchar_t *Message)
{
    ProUIMessageButton *buttons;
    ProUIMessageButton user_choice;
    ProArrayAlloc(1, sizeof(ProUIMessageButton), 1, (ProArray *)&buttons);
    buttons[0] = PRO_UI_MESSAGE_OK;
    ProUIMessageDialogDisplay(PROUIMESSAGE_INFO, L"Warning", Message, buttons, PRO_UI_MESSAGE_OK, &user_choice);
    ProArrayFree((ProArray *)&buttons);
    return PRO_TK_NO_ERROR;
}
namespace layer
{
    ProLayer layer;
    int HideAll()
    {
        ProError status;
        ProMdl mdl;
        vector<ProFeature> feat_list;
        status = ProMdlCurrentGet(&mdl);
        srand((unsigned int)time(0));
        //创建图层

        ProName layername;
        ProStringToWstring(layername, "hidetest");
        status = ProMdlLayerGet(mdl, layername, &layer);
        if (status != PRO_TK_NO_ERROR)
            status = ProLayerCreate(mdl, layername, &layer);
        //遍历模型树
        LOG(LOG_INFO) << feat_list.size();
        status = ProSolidFeatVisit((ProSolid)mdl, (ProFeatureVisitAction)HideAllActFn, assem::AsmCompFilter, (vector<ProFeature> *)&feat_list);
        LOG(LOG_INFO) << feat_list.size();
        status = ProWindowRepaint(PRO_VALUE_UNUSED);
        return 0;
    }
    ProError HideAllActFn(ProFeature *p_object, ProError status, vector<ProFeature> *app_data)
    {
        ProBoolean isVisible;
        ProFeatStatus p_status;
        ProMdl mdl, root_mdl;
        ProModelitem modelitem;
        status = ProMdlCurrentGet(&root_mdl);
        status = ProFeatureStatusGet(p_object, &p_status);
        status = ProFeatureVisibilityGet(p_object, &isVisible);
        if (isVisible == PRO_B_TRUE && p_status != PRO_FEAT_SUPPRESSED)
        {
            status = ProAsmcompMdlGet((ProAsmcomp *)(p_object), (ProMdl *)&mdl);
            status = ProMdlToModelitem(mdl, &modelitem);
            ProBoolean ishidden;
            status = ProModelitemIsHidden(&modelitem, &ishidden);
            LOG(LOG_INFO) << "id:" << modelitem.id << "\tishidden:" << ishidden;
            if (modelitem.type == PRO_ASSEMBLY)
            {
                status = ProSolidFeatVisit((ProSolid)mdl, (ProFeatureVisitAction)HideAllActFn, assem::AsmCompFilter, app_data);
            }
            else
            {
                ProLayerItem layeritem;
                status = ProLayerItemInit((ProLayerType)modelitem.type, modelitem.id, modelitem.owner, &layeritem);
                CALL_REPORT("ProLayerItemInit", "HideAllActFn", status, status != PRO_TK_NO_ERROR);
                if (status == PRO_TK_NO_ERROR)
                {
                    // status = ProModelitemHide((ProModelitem *)&layeritem);
                    // CALL_REPORT("ProModelitemHide", "HideAllActFn", status, status != PRO_TK_NO_ERROR);
                    status = ProLayerItemAdd(&layer, &layeritem);

                    CALL_REPORT("ProLayerItemAdd", "HideAllActFn", status, status != PRO_TK_NO_ERROR);
                }
            }
        }
        return PRO_TK_NO_ERROR;
    }
}
namespace SimprepModule
{
    ProSimprepdata *rep_data;
    //全部显示
    int ShowAll()
    {
        ProError err;
        //激活主表示
        //获取当前简化表示
        ProMdl mdl;
        ProSimprep rep;
        err = ProMdlCurrentGet(&mdl);
        err = ProSimprepActiveGet((ProSolid)mdl, &rep);
        //获取当前简化表示数据
        ProSimprepdata *SimpData;
        err = ProSimprepdataGet(&rep, &SimpData);
        CALL_EXIT("ProSimprepdataGet", "ShowAll", err, err != PRO_TK_NO_ERROR);
        //初始化简化表示数据
        err = ProSimprepdataAlloc(L"temprep", PRO_B_TRUE, PRO_SIMPREP_INCLUDE, &rep_data);
        CALL_EXIT("ProSimprepdataAlloc", "ShowAll", err, err != PRO_TK_NO_ERROR);
        ProAppData app_data;
        err = ProSimprepdataitemsVisit(SimpData, NULL, (ProFunction)SimprepdataitemsvisitActFn, app_data);
        CALL_EXIT("ProSimprepdataitemsVisit", "ShowAll", err, err != PRO_TK_NO_ERROR);
        //将当前简化表示设置为修改后的数据
        err = ProSimprepdataSet(&rep, rep_data);
        CALL_EXIT("ProSimprepdataSet", "ShowAll", err, err != PRO_TK_NO_ERROR);
        //释放简化表示数据变量
        err = ProSimprepdataFree(&rep_data);
        CALL_EXIT("ProSimprepdataFree", "ShowAll", err, err != PRO_TK_NO_ERROR);
        err = ProSolidDisplay((ProSolid)mdl);
        CALL_REPORT("ProSolidDisplay", "ShowAll", err, err != PRO_TK_NO_ERROR);
        return 0;
    }
    //隐藏
    int HideSel()
    {
        ProError err;
        ProSelection *p_sels = NULL;
        ProMdl mdl;
        int n_sel = 0;
        ProSimprep rep;
        err = ProMdlCurrentGet(&mdl);
        err = ProSimprepActiveGet((ProSolid)mdl, &rep);
        CALL_EXIT("ProSimprepActiveGet", "HideSel", err, err != PRO_TK_NO_ERROR);
        //初始化简化表示数据
        err = ProSimprepdataAlloc(L"temprep", PRO_B_TRUE, PRO_SIMPREP_INCLUDE, &rep_data);
        CALL_EXIT("ProSimprepdataAlloc", "HideSel", err, err != PRO_TK_NO_ERROR);
        ProSimprepType rep_type;
        err = ProSimprepTypeGet(&rep, &rep_type);
        if (rep_type != PRO_SIMPREP_MASTER_REP)
        {
            ProSimprepdata *current_rep_data = NULL;
            err = ProSimprepdataGet(&rep, &current_rep_data);
            CALL_REPORT("ProSimprepdataGet", "HideSel", err, err != PRO_TK_NO_ERROR);

            ProAppData app_data;
            err = ProSimprepdataitemsVisit(current_rep_data, NULL, (ProFunction)SimprepdataCopy, app_data);
            CALL_EXIT("ProSimprepdataitemsVisit", "HideSel", err, err != PRO_TK_NO_ERROR);
        }
        //获取当前选择的模型
        err = ProSelbufferSelectionsGet(&p_sels);
        CALL_EXIT("ProSelbufferSelectionsGet", "HideSel", err, err != PRO_TK_NO_ERROR);
        err = ProArraySizeGet(p_sels, &n_sel);
        CALL_EXIT("ProArraySizeGet", "HideSel", err, err != PRO_TK_NO_ERROR);
        if (n_sel > 0)
        {
            for (int i = 0; i < n_sel; i++)
            {
                SimprepdataitemAdd(rep, p_sels[i], PRO_SIMPREP_EXCLUDE);
            }
            err = ProSimprepdataSet(&rep, rep_data);
            CALL_REPORT("ProSimprepdataSet", "HideSel", err, err != PRO_TK_NO_ERROR);
            if (err != PRO_TK_NO_ERROR)
            {
                ProSimprep new_rep;
                err = ProSimprepCreate((ProSolid)mdl, rep_data, &new_rep);
                CALL_EXIT("ProSimprepCreate", "HideSel", err, err != PRO_TK_NO_ERROR);
                err = ProSimprepdataSet(&new_rep, rep_data);
                CALL_EXIT("ProSimprepdataSet", "HideSel", err, err != PRO_TK_NO_ERROR);
                err = ProSimprepActivate((ProSolid)mdl, &new_rep);
            }
            //释放简化表示数据变量
            err = ProSimprepdataFree(&rep_data);
            CALL_EXIT("ProSimprepdataFree", "HideSel", err, err != PRO_TK_NO_ERROR);
            err = ProSolidDisplay((ProSolid)mdl);
        }
        return 0;
    }
    //只显示
    int ShowSel()
    {
        //选择模型
        //创建简化表示
        //遍历模型
        //将选择的模型设置为显示，其余模型设置为不显示
        return 0;
    }
    //反向显示
    int ReHide()
    {
        //遍历模型全部隐藏
        ProError err;
        ProMdl mdl;
        err = ProMdlCurrentGet(&mdl);
        //初始化简化表示数据
        err = ProSimprepdataAlloc(L"temprep", PRO_B_TRUE, PRO_SIMPREP_INCLUDE, &rep_data);
        CALL_EXIT("ProSimprepdataAlloc", "ReHide", err, err != PRO_TK_NO_ERROR);
        ProAppData app_data;
        err = ProSolidFeatVisit((ProSolid)mdl, (ProFeatureVisitAction)HideitemActFn, assem::AsmCompFilter, app_data);
        //检索当前表示反显
        ProSimprep rep;
        err = ProSimprepActiveGet((ProSolid)mdl, &rep);
        ProSimprepdata *old_rep_data;
        err = ProSimprepdataGet(&rep, &old_rep_data);
        err = ProSimprepdataitemsVisit(old_rep_data, NULL, (ProFunction)SimprepdataRev, app_data);
        CALL_EXIT("ProSimprepdataitemsVisit", "ReHide", err, err != PRO_TK_NO_ERROR);
        ProFeature feat;
        err = ProFeatureInit((ProSolid)mdl, NULL, &feat);
        ProSelection sel;
        err = ProFeatureSelectionGet(&feat, &sel);
        SimprepdataitemAdd(rep, sel, PRO_SIMPREP_INCLUDE);
        err = ProSimprepdataSet(&rep, rep_data);
        //释放简化表示数据变量
        err = ProSimprepdataFree(&rep_data);
        CALL_EXIT("ProSimprepdataFree", "ReHide", err, err != PRO_TK_NO_ERROR);
        err = ProSolidDisplay((ProSolid)mdl);
        return 0;
    }
    ProError SimprepdataitemsvisitActFn(ProSimprepitem *item, ProError err, ProAppData app_data)
    {
        item->action.type = PRO_SIMPREP_INCLUDE;
        err = ProSimprepdataitemAdd(rep_data, item);
        CALL_REPORT("ProSimprepdataitemAdd", "SimprepdataitemsvisitActFn", err, err != PRO_TK_NO_ERROR);
        return PRO_TK_NO_ERROR;
    }
    ProError SimprepdataCopy(ProSimprepitem *item, ProError err, ProAppData app_data)
    {
        err = ProSimprepdataitemAdd(rep_data, item);
        CALL_REPORT("ProSimprepdataitemAdd", "SimprepdataitemsvisitActFn", err, err != PRO_TK_NO_ERROR);
        return PRO_TK_NO_ERROR;
    }
    ProError SimprepdataRev(ProSimprepitem *item, ProError err, ProAppData app_data)
    {
        if (item->action.type != PRO_SIMPREP_INCLUDE)
        {
            item->action.type = PRO_SIMPREP_EXCLUDE;
        }
        else
        {
            item->action.type = PRO_SIMPREP_INCLUDE;
        }
        err = ProSimprepdataitemAdd(rep_data, item);
        CALL_REPORT("ProSimprepdataitemAdd", "SimprepdataitemsvisitActFn", err, err != PRO_TK_NO_ERROR);
        return PRO_TK_NO_ERROR;
    }
    int SimprepdataitemAdd(ProSimprep rep, ProSelection sel, ProSimprepActionType act_type)
    {
        ProError err;
        ProModelitem modelitem;
        err = ProSelectionModelitemGet(sel, &modelitem);
        CALL_EXIT("ProSelectionModelitemGet", "HideSel", err, err != PRO_TK_NO_ERROR);
        ProSimprepitem rep_item;
        ProAsmcomppath comppath;
        err = ProSelectionAsmcomppathGet(sel, &comppath);
        ProSubstitution subst;
        err = ProSubstitutionInit(PRO_SUBST_NONE, PRO_VALUE_UNUSED, NULL, &rep, &subst);
        CALL_EXIT("ProSubstitutionInit", "HideSel", err, err != PRO_TK_NO_ERROR);
        ProSimprepAction rep_act;
        err = ProSimprepActionInit(act_type, &subst, &rep_act);
        CALL_EXIT("ProSimprepActionInit", "HideSel", err, err != PRO_TK_NO_ERROR);
        err = ProSimprepdataitemInit(comppath.comp_id_table, comppath.table_num, modelitem.id, &rep_act, &rep_item);
        CALL_EXIT("ProSimprepdataitemInit", "HideSel", err, err != PRO_TK_NO_ERROR);
        err = ProSimprepdataitemAdd(rep_data, &rep_item);
        CALL_EXIT("ProSimprepdataitemAdd", "HideSel", err, err != PRO_TK_NO_ERROR);
        return 0;
    }
    ProError HideitemActFn(ProFeature *feat, ProError err, ProAppData app_data)
    {
        ProSelection sel;
        err = ProFeatureSelectionGet(feat, &sel);
        ProSimprep rep;
        err = ProSimprepActiveGet((ProSolid)(*feat).owner, &rep);
        SimprepdataitemAdd(rep, sel, PRO_SIMPREP_EXCLUDE);
        return err;
    }
}

//主程序

#if Asynchronous
//异步模式
int main(int argc, char *argv[])
{
    HWND hWnd = GetForegroundWindow();
    // TopWindow(hWnd);
    GetDllPath(dllpath);
    for (int i = 0; i < 3; i++)
    {
        LogFile[i] = dllpath + LogFile[i];
    }
    initLogger(LogFile[0], LogFile[1], LogFile[2]);
    cout << "Connecting..." << endl;
    pfcAsyncConnection_ptr connection;
    try
    {
        connection = pfcAsyncConnection::Connect(NULL, NULL, NULL, 10);
        cout << "Connect Success." << endl;
        pfcSession_ptr session = connection->GetSession();
        while (1)
        {
            cout << "action?";
            char flag = 'Y';
            cin >> flag;
            if (flag == 'Y')
                Async_Action(session);
            else
                break;
        }
    }
    OTK_EXCEPTION_PRINT_LOG
    catch (...)
    {
        cout << "Connect Failed!" << endl;
    }
    system("pause");
    if (connection)
        connection->Disconnect(10);
    cleanlog();
    return 0;
}
#else
//程序入口
extern "C" int user_initialize(
    int argc,
    char *argv[],
    char *version[],
    char *build,
    wchar_t errbuf[80])
{

    ProError err;

    ProStringToWstring(msg_filename, MSGFILE);
    GetDllPath(dllpath);
    for (int i = 0; i < 3; i++)
    {
        LogFile[i] = dllpath + LogFile[i];
    }
    initLogger(LogFile[0], LogFile[1], LogFile[2]);

    err = ProMenubarMenuAdd((char *)"CreoTool", (char *)"CreoTool", NULL, PRO_B_TRUE, msg_filename);
    int id_i = 0;
    typedef int (*CmdActFn)();
    uiCmdCmdId CmdId[20];
    CmdActFn action[] = {drawingModule::OpenDrw,
                         drawingModule::CreateDrw,
                         assem::ColorPaint,
                         lua_test, sqlite_test,
                         SimprepModule::ShowAll, SimprepModule::HideSel, SimprepModule::ReHide,
                         layer::HideAll,
                         Info};
    char *action_name[] = {"OpenDrw", "CreateDrw", "ColorPaint", "lua_test", "sqlite_test", "ShowAll", "HideSel", "ReHide", "HideAll", "Info"};
    char *mapkey[] = {"sod", "scd", "scp", "slt", "sqt", "ssa", "shs", "srh", "sha", "sif"};
    for (int i = 0; i < sizeof(action) / sizeof(action[0]); i++)
    {
        err = ProCmdActionAdd(action_name[i], (uiCmdCmdActFn)action[i], uiProe2ndImmediate, DefaultAccess, PRO_B_TRUE, PRO_B_TRUE, &(CmdId[i]));
        err = ProMenubarmenuPushbuttonAdd((char *)ProjectName, action_name[i], action_name[i], action_name[i], NULL, PRO_B_TRUE, CmdId[i], msg_filename);
        ProName option;
        ProPath opt_value;
        char mapkey_value[MAPKEY_SIZE];
        ProStringToWstring(option, "mapkey");
        ProTKSprintf(mapkey_value, "%s @MAPKEY_LABEL%s; ~ Command `%s`;", mapkey[i], action_name[i], action_name[i]);
        ProStringToWstring(opt_value, mapkey_value);
        err = ProConfigoptSet(option, opt_value);
    }

    //创建插件启动和停止快捷键
    ProName option;
    ProStringToWstring(option, "mapkey");
    ProPath opt_value;
    char start_value[MAPKEY_SIZE];
    char stop_value[MAPKEY_SIZE];
    char *tmp_value[] = {"%s @MAPKEY_LABEL%s %s; ",
                         "~ Activate `main_dlg_cur` `page_Tools_control_btn` 1; ",
                         "~ Command `ProCmdUtilAux`; ",
                         " ~ Select `aux_apps` `AppList` 1 `%s`; ",
                         "~ Activate `aux_apps` `%s`; ",
                         "~ Activate `aux_apps` `CloseBtn`;"};
    char *tmp_value_combine = (char *)malloc(MAPKEY_SIZE);
    //初始tmp_value_combine非空，直接strcat前面会有乱码
    strcpy(tmp_value_combine, tmp_value[0]);
    for (int s = 1; s < sizeof(tmp_value) / sizeof(tmp_value[0]); s++)
    {
        strcat(tmp_value_combine, tmp_value[s]);
    }
    ProTKSprintf(start_value, tmp_value_combine, "st", "start", (char *)ProjectName, (char *)ProjectName, "StartBtn");
    ProStringToWstring(opt_value, start_value);
    err = ProConfigoptSet(option, opt_value);
    ProTKSprintf(stop_value, tmp_value_combine, "sp", "stop", (char *)ProjectName, (char *)ProjectName, "StopBtn");
    ProStringToWstring(opt_value, stop_value);
    err = ProConfigoptSet(option, opt_value);
    return 0;
}
//程序出口
extern "C" void user_terminate()
{
    cleanlog();
}
#endif
